/*
 * JUPPCPP is driven by a simple lexer.
 *
 * We effectively add three C-style preprocessing commands: 'aspect', 'case',
 * and 'endcase'. The 'aspect' command is to be used only once per file -
 * everything else in that source file is to be considered part of that aspect.
 * (Theoretically, it may be possible to create an aspect spanning multiple
 * source files, but you really shouldn't.) The 'case'/'endcase' pair is to
 * surround a single test case.
 */

%{

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ASPECT_NAME_MAX 100

void _aspect();
void _case(char *);
void _endcase();

void syntax_error() {
	fprintf(stderr, "Syntax error\n");
	abort();
}

int in_case=0;

%}

%s CASE
%s CASE1

%%

<INITIAL>{
#aspect				_aspect();
#case				BEGIN(CASE);
#endcase			_endcase();
}

<CASE>{
[a-zA-Z][a-zA-Z0-9]*		_case(yytext); BEGIN(CASE1);
[ \t]				/* whitespace - ignored */
.				syntax_error();
}

<CASE1>{
[ \t]				/* whitespace - ignored */
\n				BEGIN(INITIAL);
.				syntax_error();
}

%%

/* Called when #aspect is encountered. */
void _aspect() {
	char c = input();
	char *namebuf = malloc(ASPECT_NAME_MAX+1);
	short namelen = 0;

	while (c != '\"') {
		if (c == '\n')
			syntax_error();
		c = input();
	}
	c = input();
	while (c != '\"') {
		if (c == '\n') {
			fprintf(stderr, "Syntax error\n");
			abort();
		}
		namebuf[namelen++] = c;
		if (namelen >= ASPECT_NAME_MAX-1)
			break;
		c = input();
	}
	namebuf[namelen] = '\0';
	if (input() != '\n') {
		fprintf(stderr, "Syntax error\n");
		abort();
	}

	fprintf(yyout, "char *aspect_name = \"%s\";\n", namebuf);
}

/* Called when #case is encountered. */
void _case(char *name) {
	static int case_no = 0;
	if (in_case)
		syntax_error();
	fprintf(yyout, "void jamunit_case_%s_%d {\n", name, case_no++);
	in_case = 1;
}

/* Called when #endcase is encountered. */
void _endcase() {
	fprintf(yyout, "}\n");
	in_case = 0;
}

